#ifndef Queue_h
#define Queue_h

#include "SingleNode.h"


namespace TL {
    template<class T> class Queue {
    protected:
        SingleNode<T> *m_Head, *m_Tail;
        int m_Size;

    protected:
        void zeroing()
        {
            m_Head = 0;
            m_Tail = 0;

            m_Size = 0;
        }

    public:
        Queue()
        {
            zeroing();
        }
        ~Queue()
        {
            Clear();
        }

        void Clear()
        {
            SingleNode<T> *removed_node;
            SingleNode<T> *target_node = m_Head;

            while (target_node) {
                removed_node = target_node;
                target_node = target_node->GetNext();

                delete removed_node;
            }

            zeroing();
        }
        bool IsEmpty() const
        {
            return (m_Size == 0);
        }
        T Pop()
        {
            T return_value;

            if (m_Size > 1) {
                return_value = m_Head->GetData();

                SingleNode<T> *removed_node = m_Head;

                m_Head = m_Head->GetNext();

                delete removed_node;

                m_Size--;
            }
            else if (m_Size == 1) {
                return_value = m_Head->GetData();

                delete m_Head;

                zeroing();
            }
            else {
                return_value = T();
            }

            return return_value;
        }
        void Push(const T &value)
        {
            SingleNode<T> *new_node = new SingleNode<T>(value);

            if (m_Size != 0) {
                m_Tail->SetNext(new_node);
            }
            else {
                m_Head = new_node;
            }

            m_Tail = new_node;

            m_Size++;
        }
        int Size() const
        {
            return m_Size;
        }
    };
}

#endif
